//
// Created by EmFi on 2023/5/19.
//

#ifndef DBMS_FILLUTIL_H
#define DBMS_FILLUTIL_H

#include <list>
#include <iostream>
#include <set>
#include <map>
#include "../Database/Point.h"

using namespace std;

class FillUtil {
public:
    static bool checkEmpty(const list<Point>& list, bool printDetail = false) {
        int total = 0;
        int i = 0;
        for (auto it : list) {
            i++;
            if (!it.check()) {
                if (printDetail) {
                    cout << "Found unfulfilled object at line " << i << " " << it << endl;
                }
                total++;
            }
        }
        cout << "Empty check finished, total " << total << endl;
        return total == 0;
    }

    static bool checkDuplicate(const list<Point>& list, bool printDetail = false) {
        bool flag = true;
        map<double, ::list<Point>> mapX;
        map<double, ::list<Point>> mapY;
        map<double, ::list<Point>> mapZ;
        map<double, ::list<Point>> mapW;
        for (auto it : list) {
            mapX[it.getX()].push_back(it);
            mapY[it.getY()].push_back(it);
            mapZ[it.getZ()].push_back(it);
            mapW[it.getW()].push_back(it);
        }
        for (const auto& item: mapX) {
            if (item.second.size() != 1) {
                flag = false;
                if (printDetail) {
                    cout << "X duplicated: ";
                    for (auto it : item.second) {
                        cout << it << "\t";
                    }
                    cout << endl;
                }
            }
        }
        for (const auto& item: mapY) {
            if (item.second.size() != 1) {
                flag = false;
                if (printDetail) {
                    cout << "Y duplicated: ";
                    for (auto it: item.second) {
                        cout << it << "\t";
                    }
                    cout << endl;
                }
            }
        }
        for (const auto& item: mapZ) {
            if (item.second.size() != 1) {
                flag = false;
                if (printDetail) {
                    cout << "Z duplicated: ";
                    for (auto it: item.second) {
                        cout << it << "\t";
                    }
                    cout << endl;
                }
            }
        }
        for (const auto& item: mapW) {
            if (item.second.size() != 1) {
                flag = false;
                if (printDetail) {
                    cout << "W duplicated: ";
                    for (auto it: item.second) {
                        cout << it << "\t";
                    }
                    cout << endl;
                }
            }
        }
        cout << "Duplicate check finished, result " << flag << endl;
        return flag;
    }

    static void fill(list<Point>& list) {
        int i = 0;
        for (auto &it : list) {
            if (!it.check()) {
                it.fill();
                i++;
            }
        }
        cout << "Fill finished, total " << i << endl;
    }
};

#endif //DBMS_FILLUTIL_H
